"""
State Manager for Desktop Application
桌面应用状态管理器
"""

import json
import logging
import importlib.util
from typing import Optional, Dict, Any, List, Callable
from pathlib import Path
from datetime import datetime, timedelta
import asyncio

logger = logging.getLogger(__name__)


class AppState:
    """应用状态类"""
    
    def __init__(self):
        self.user_info: Optional[Dict[str, Any]] = None
        self.auth_token: Optional[str] = None
        self.current_view: str = "auth"
        self.content_list: List[Dict[str, Any]] = []
        self.folder_tree: List[Dict[str, Any]] = []
        self.tag_list: List[Dict[str, Any]] = []
        self.selected_content: Optional[Dict[str, Any]] = None
        self.selected_folder: Optional[Dict[str, Any]] = None
        self.generation_tasks: List[Dict[str, Any]] = []
        self.app_settings: Dict[str, Any] = {
            "theme": "system",  # light, dark, system
            "language": "zh-CN",
            "auto_save": True,
            "notifications": True,
            "max_concurrent_generations": 3,
            "default_ai_provider": "doubao",
            "save_credentials": False,
        }
        self.last_sync_time: Optional[datetime] = None
        self.is_online: bool = True


class StateManager:
    """状态管理器类"""
    
    def __init__(self, config_dir: Optional[str] = None):
        self.state = AppState()
        self.config_dir = Path(config_dir or self._get_default_config_dir())
        self.state_file = self.config_dir / "app_state.json"
        self.settings_file = self.config_dir / "settings.json"
        self.credentials_file = self.config_dir / "credentials.json"
        self.callbacks: Dict[str, List[Callable]] = {}
        self._lock = asyncio.Lock()
        
        # 确保配置目录存在
        self.config_dir.mkdir(parents=True, exist_ok=True)
    
    def _get_default_config_dir(self) -> Path:
        """获取默认配置目录"""
        if importlib.util.find_spec("flet"):
            # 在桌面环境中使用用户配置目录
            import os
            return Path.home() / ".media_create_desktop"
        else:
            # 在开发环境中使用当前目录
            return Path.cwd() / "config"
    
    async def initialize(self) -> None:
        """初始化状态管理器"""
        try:
            logger.info("Initializing state manager")
            
            # 加载保存的状态
            await self.load_state()
            await self.load_settings()
            
            logger.info("State manager initialized successfully")
            
        except Exception as e:
            logger.error(f"Failed to initialize state manager: {e}")
            # 使用默认状态继续
    
    async def cleanup(self) -> None:
        """清理状态管理器"""
        try:
            logger.info("Cleaning up state manager")
            
            # 保存当前状态
            await self.save_state()
            await self.save_settings()
            
            logger.info("State manager cleanup completed")
            
        except Exception as e:
            logger.error(f"Error during state manager cleanup: {e}")
    
    # 用户状态管理
    async def set_user(self, user_info: Dict[str, Any]) -> None:
        """设置用户信息"""
        async with self._lock:
            self.state.user_info = user_info
            await self.save_state()
            await self._notify_callbacks("user_changed", user_info)
            logger.info(f"User state updated: {user_info.get('username', 'Unknown')}")
    
    async def get_user(self) -> Optional[Dict[str, Any]]:
        """获取用户信息"""
        return self.state.user_info
    
    async def clear_user(self) -> None:
        """清除用户信息"""
        async with self._lock:
            old_user = self.state.user_info
            self.state.user_info = None
            await self.save_state()
            await self._notify_callbacks("user_changed", None)
            logger.info("User state cleared")
    
    async def is_authenticated(self) -> bool:
        """检查是否已认证"""
        return self.state.user_info is not None and self.state.auth_token is not None
    
    async def get_user_id(self) -> Optional[str]:
        """获取用户ID"""
        if self.state.user_info:
            return self.state.user_info.get("user_id")
        return None
    
    async def get_username(self) -> Optional[str]:
        """获取用户名"""
        if self.state.user_info:
            return self.state.user_info.get("username")
        return None
    
    # 认证令牌管理
    async def save_token(self, token: str) -> None:
        """保存认证令牌"""
        async with self._lock:
            self.state.auth_token = token
            await self.save_state()
            
            # 如果设置了保存凭据，也保存到安全存储
            if self.state.app_settings.get("save_credentials", False):
                await self._save_credentials_securely({"token": token})
            
            logger.info("Authentication token saved")
    
    async def get_token(self) -> Optional[str]:
        """获取认证令牌"""
        if self.state.auth_token:
            return self.state.auth_token
        
        # 尝试从安全存储加载
        if self.state.app_settings.get("save_credentials", False):
            credentials = await self._load_credentials_securely()
            return credentials.get("token")
        
        return None
    
    async def clear_token(self) -> None:
        """清除认证令牌"""
        async with self._lock:
            self.state.auth_token = None
            await self.save_state()
            
            # 清除安全存储中的凭据
            await self._clear_credentials_securely()
            
            logger.info("Authentication token cleared")
    
    async def has_valid_token(self) -> bool:
        """检查是否有有效的认证令牌"""
        token = await self.get_token()
        if not token:
            return False
        
        # TODO: 验证令牌是否过期
        # 这里应该检查令牌的过期时间
        return True
    
    # 视图状态管理
    async def set_current_view(self, view_name: str) -> None:
        """设置当前视图"""
        async with self._lock:
            old_view = self.state.current_view
            self.state.current_view = view_name
            await self.save_state()
            await self._notify_callbacks("view_changed", {
                "old_view": old_view,
                "new_view": view_name
            })
            logger.info(f"View changed: {old_view} -> {view_name}")
    
    async def get_current_view(self) -> str:
        """获取当前视图"""
        return self.state.current_view
    
    # 内容管理
    async def set_content_list(self, content_list: List[Dict[str, Any]]) -> None:
        """设置内容列表"""
        async with self._lock:
            self.state.content_list = content_list
            self.state.last_sync_time = datetime.utcnow()
            await self.save_state()
            await self._notify_callbacks("content_list_changed", content_list)
            logger.info(f"Content list updated: {len(content_list)} items")
    
    async def get_content_list(self) -> List[Dict[str, Any]]:
        """获取内容列表"""
        return self.state.content_list
    
    async def add_content(self, content: Dict[str, Any]) -> None:
        """添加内容"""
        async with self._lock:
            self.state.content_list.append(content)
            self.state.last_sync_time = datetime.utcnow()
            await self.save_state()
            await self._notify_callbacks("content_added", content)
            logger.info(f"Content added: {content.get('id', 'Unknown')}")
    
    async def update_content(self, content_id: str, updates: Dict[str, Any]) -> None:
        """更新内容"""
        async with self._lock:
            for i, content in enumerate(self.state.content_list):
                if content.get("id") == content_id:
                    self.state.content_list[i].update(updates)
                    self.state.last_sync_time = datetime.utcnow()
                    await self.save_state()
                    await self._notify_callbacks("content_updated", {
                        "content_id": content_id,
                        "updates": updates
                    })
                    logger.info(f"Content updated: {content_id}")
                    break
    
    async def remove_content(self, content_id: str) -> None:
        """移除内容"""
        async with self._lock:
            self.state.content_list = [
                content for content in self.state.content_list
                if content.get("id") != content_id
            ]
            self.state.last_sync_time = datetime.utcnow()
            await self.save_state()
            await self._notify_callbacks("content_removed", {"content_id": content_id})
            logger.info(f"Content removed: {content_id}")
    
    async def set_selected_content(self, content: Optional[Dict[str, Any]]) -> None:
        """设置选中的内容"""
        async with self._lock:
            self.state.selected_content = content
            await self.save_state()
            await self._notify_callbacks("content_selected", content)
            logger.info(f"Content selected: {content.get('id', 'None') if content else 'None'}")
    
    async def get_selected_content(self) -> Optional[Dict[str, Any]]:
        """获取选中的内容"""
        return self.state.selected_content
    
    # 文件夹管理
    async def set_folder_tree(self, folder_tree: List[Dict[str, Any]]) -> None:
        """设置文件夹树"""
        async with self._lock:
            self.state.folder_tree = folder_tree
            await self.save_state()
            await self._notify_callbacks("folder_tree_changed", folder_tree)
            logger.info(f"Folder tree updated: {len(folder_tree)} folders")
    
    async def get_folder_tree(self) -> List[Dict[str, Any]]:
        """获取文件夹树"""
        return self.state.folder_tree
    
    async def set_selected_folder(self, folder: Optional[Dict[str, Any]]) -> None:
        """设置选中的文件夹"""
        async with self._lock:
            self.state.selected_folder = folder
            await self.save_state()
            await self._notify_callbacks("folder_selected", folder)
            logger.info(f"Folder selected: {folder.get('id', 'None') if folder else 'None'}")
    
    async def get_selected_folder(self) -> Optional[Dict[str, Any]]:
        """获取选中的文件夹"""
        return self.state.selected_folder
    
    # 标签管理
    async def set_tag_list(self, tag_list: List[Dict[str, Any]]) -> None:
        """设置标签列表"""
        async with self._lock:
            self.state.tag_list = tag_list
            await self.save_state()
            await self._notify_callbacks("tag_list_changed", tag_list)
            logger.info(f"Tag list updated: {len(tag_list)} tags")
    
    async def get_tag_list(self) -> List[Dict[str, Any]]:
        """获取标签列表"""
        return self.state.tag_list
    
    # 生成任务管理
    async def set_generation_tasks(self, tasks: List[Dict[str, Any]]) -> None:
        """设置生成任务列表"""
        async with self._lock:
            self.state.generation_tasks = tasks
            await self.save_state()
            await self._notify_callbacks("generation_tasks_changed", tasks)
            logger.info(f"Generation tasks updated: {len(tasks)} tasks")
    
    async def get_generation_tasks(self) -> List[Dict[str, Any]]:
        """获取生成任务列表"""
        return self.state.generation_tasks
    
    async def add_generation_task(self, task: Dict[str, Any]) -> None:
        """添加生成任务"""
        async with self._lock:
            self.state.generation_tasks.append(task)
            await self.save_state()
            await self._notify_callbacks("generation_task_added", task)
            logger.info(f"Generation task added: {task.get('id', 'Unknown')}")
    
    async def update_generation_task(self, task_id: str, updates: Dict[str, Any]) -> None:
        """更新生成任务"""
        async with self._lock:
            for i, task in enumerate(self.state.generation_tasks):
                if task.get("id") == task_id:
                    self.state.generation_tasks[i].update(updates)
                    await self.save_state()
                    await self._notify_callbacks("generation_task_updated", {
                        "task_id": task_id,
                        "updates": updates
                    })
                    logger.info(f"Generation task updated: {task_id}")
                    break
    
    async def remove_generation_task(self, task_id: str) -> None:
        """移除生成任务"""
        async with self._lock:
            self.state.generation_tasks = [
                task for task in self.state.generation_tasks
                if task.get("id") != task_id
            ]
            await self.save_state()
            await self._notify_callbacks("generation_task_removed", {"task_id": task_id})
            logger.info(f"Generation task removed: {task_id}")
    
    # 设置管理
    async def set_setting(self, key: str, value: Any) -> None:
        """设置应用配置"""
        async with self._lock:
            self.state.app_settings[key] = value
            await self.save_settings()
            await self._notify_callbacks("setting_changed", {"key": key, "value": value})
            logger.info(f"Setting changed: {key} = {value}")
    
    async def get_setting(self, key: str, default: Any = None) -> Any:
        """获取应用配置"""
        return self.state.app_settings.get(key, default)
    
    async def get_all_settings(self) -> Dict[str, Any]:
        """获取所有应用配置"""
        return self.state.app_settings.copy()
    
    async def set_theme(self, theme: str) -> None:
        """设置主题"""
        if theme in ["light", "dark", "system"]:
            await self.set_setting("theme", theme)
    
    async def get_theme(self) -> str:
        """获取主题"""
        return await self.get_setting("theme", "system")
    
    # 状态持久化
    async def save_state(self) -> None:
        """保存状态到文件"""
        try:
            state_data = {
                "user_info": self.state.user_info,
                "auth_token": self.state.auth_token,
                "current_view": self.state.current_view,
                "content_list": self.state.content_list,
                "folder_tree": self.state.folder_tree,
                "tag_list": self.state.tag_list,
                "selected_content": self.state.selected_content,
                "selected_folder": self.state.selected_folder,
                "generation_tasks": self.state.generation_tasks,
                "last_sync_time": self.state.last_sync_time.isoformat() if self.state.last_sync_time else None,
                "is_online": self.state.is_online,
                "version": "1.0.0"
            }
            
            async with aiofiles.open(self.state_file, 'w', encoding='utf-8') as f:
                await f.write(json.dumps(state_data, ensure_ascii=False, indent=2))
            
            logger.debug("Application state saved successfully")
            
        except Exception as e:
            logger.error(f"Failed to save application state: {e}")
            raise
    
    async def load_state(self) -> None:
        """从文件加载状态"""
        try:
            if not self.state_file.exists():
                logger.info("No saved state file found, using default state")
                return
            
            async with aiofiles.open(self.state_file, 'r', encoding='utf-8') as f:
                content = await f.read()
                state_data = json.loads(content)
            
            # 恢复状态
            self.state.user_info = state_data.get("user_info")
            self.state.auth_token = state_data.get("auth_token")
            self.state.current_view = state_data.get("current_view", "auth")
            self.state.content_list = state_data.get("content_list", [])
            self.state.folder_tree = state_data.get("folder_tree", [])
            self.state.tag_list = state_data.get("tag_list", [])
            self.state.selected_content = state_data.get("selected_content")
            self.state.selected_folder = state_data.get("selected_folder")
            self.state.generation_tasks = state_data.get("generation_tasks", [])
            
            if state_data.get("last_sync_time"):
                self.state.last_sync_time = datetime.fromisoformat(state_data["last_sync_time"])
            
            self.state.is_online = state_data.get("is_online", True)
            
            logger.info("Application state loaded successfully")
            
        except Exception as e:
            logger.error(f"Failed to load application state: {e}")
            # 使用默认状态继续
    
    async def save_settings(self) -> None:
        """保存设置到文件"""
        try:
            async with aiofiles.open(self.settings_file, 'w', encoding='utf-8') as f:
                await f.write(json.dumps(self.state.app_settings, ensure_ascii=False, indent=2))
            
            logger.debug("Application settings saved successfully")
            
        except Exception as e:
            logger.error(f"Failed to save application settings: {e}")
            raise
    
    async def load_settings(self) -> None:
        """从文件加载设置"""
        try:
            if not self.settings_file.exists():
                logger.info("No saved settings file found, using default settings")
                return
            
            async with aiofiles.open(self.settings_file, 'r', encoding='utf-8') as f:
                content = await f.read()
                settings_data = json.loads(content)
            
            self.state.app_settings.update(settings_data)
            logger.info("Application settings loaded successfully")
            
        except Exception as e:
            logger.error(f"Failed to load application settings: {e}")
            # 使用默认设置继续
    
    # 安全凭据存储（简化版）
    async def _save_credentials_securely(self, credentials: Dict[str, Any]) -> None:
        """安全保存凭据（简化版）"""
        try:
            # 在实际应用中，这里应该使用更安全的加密存储
            async with aiofiles.open(self.credentials_file, 'w', encoding='utf-8') as f:
                await f.write(json.dumps(credentials, ensure_ascii=False, indent=2))
            
            # 设置文件权限（在支持的系统上）
            try:
                self.credentials_file.chmod(0o600)  # 仅所有者可读写
            except Exception:
                pass  # 某些系统可能不支持
            
            logger.debug("Credentials saved securely")
            
        except Exception as e:
            logger.error(f"Failed to save credentials securely: {e}")
            raise
    
    async def _load_credentials_securely(self) -> Dict[str, Any]:
        """安全加载凭据（简化版）"""
        try:
            if not self.credentials_file.exists():
                return {}
            
            async with aiofiles.open(self.credentials_file, 'r', encoding='utf-8') as f:
                content = await f.read()
                return json.loads(content)
            
        except Exception as e:
            logger.error(f"Failed to load credentials securely: {e}")
            return {}
    
    async def _clear_credentials_securely(self) -> None:
        """安全清除凭据"""
        try:
            if self.credentials_file.exists():
                self.credentials_file.unlink()
                logger.debug("Credentials cleared securely")
            
        except Exception as e:
            logger.error(f"Failed to clear credentials securely: {e}")
    
    # 回调管理
    def add_callback(self, event_type: str, callback: Callable) -> None:
        """添加事件回调"""
        if event_type not in self.callbacks:
            self.callbacks[event_type] = []
        self.callbacks[event_type].append(callback)
    
    def remove_callback(self, event_type: str, callback: Callable) -> None:
        """移除事件回调"""
        if event_type in self.callbacks:
            self.callbacks[event_type] = [
                cb for cb in self.callbacks[event_type] 
                if cb != callback
            ]
    
    async def _notify_callbacks(self, event_type: str, data: Any) -> None:
        """通知事件回调"""
        if event_type in self.callbacks:
            for callback in self.callbacks[event_type]:
                try:
                    if asyncio.iscoroutinefunction(callback):
                        await callback(data)
                    else:
                        callback(data)
                except Exception as e:
                    logger.error(f"Callback error for event {event_type}: {e}")
    
    # 网络状态管理
    async def set_online_status(self, is_online: bool) -> None:
        """设置网络状态"""
        if self.state.is_online != is_online:
            self.state.is_online = is_online
            await self._notify_callbacks("online_status_changed", is_online)
            logger.info(f"Online status changed: {is_online}")
    
    async def is_online(self) -> bool:
        """检查是否在线"""
        return self.state.is_online
    
    # 同步状态管理
    async def mark_sync_complete(self) -> None:
        """标记同步完成"""
        self.state.last_sync_time = datetime.utcnow()
        await self.save_state()
        await self._notify_callbacks("sync_completed", self.state.last_sync_time)
        logger.info("Data synchronization completed")
    
    async def get_last_sync_time(self) -> Optional[datetime]:
        """获取最后同步时间"""
        return self.state.last_sync_time
    
    async def needs_sync(self, max_age_minutes: int = 5) -> bool:
        """检查是否需要同步"""
        if not self.state.last_sync_time:
            return True
        
        age = datetime.utcnow() - self.state.last_sync_time
        return age.total_seconds() > (max_age_minutes * 60)
    
    # 重置状态
    async def reset_state(self) -> None:
        """重置所有状态（除了设置）"""
        async with self._lock:
            self.state.user_info = None
            self.state.auth_token = None
            self.state.current_view = "auth"
            self.state.content_list = []
            self.state.folder_tree = []
            self.state.tag_list = []
            self.state.selected_content = None
            self.state.selected_folder = None
            self.state.generation_tasks = []
            self.state.last_sync_time = None
            self.state.is_online = True
            
            await self.save_state()
            await self._notify_callbacks("state_reset", None)
            logger.info("Application state reset")
    
    # 获取状态摘要
    def get_state_summary(self) -> Dict[str, Any]:
        """获取状态摘要"""
        return {
            "is_authenticated": self.state.user_info is not None,
            "current_view": self.state.current_view,
            "content_count": len(self.state.content_list),
            "folder_count": len(self.state.folder_tree),
            "tag_count": len(self.state.tag_list),
            "task_count": len(self.state.generation_tasks),
            "last_sync_time": self.state.last_sync_time.isoformat() if self.state.last_sync_time else None,
            "is_online": self.state.is_online,
            "theme": self.state.app_settings.get("theme", "system"),
        }


# 全局状态管理器实例
state_manager = StateManager()


# 导出
__all__ = ["StateManager", "AppState", "state_manager"]